package com.bitrate.dagger.server.websocket.handler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.http.common.HttpResponseStatus;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsResponse;
import org.tio.websocket.server.handler.IWsMsgHandler;

import com.bitrate.dagger.sdk.websocket.enums.PushBizType;
import com.bitrate.dagger.sdk.websocket.request.WebSocketRequest;
import com.bitrate.dagger.server.websocket.auth.Transmitter;
import com.bitrate.dagger.server.websocket.cache.LocalCache;
import com.google.gson.Gson;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class WebSocketHandler implements IWsMsgHandler {

	@Autowired
	private WebSocketStrategyContext webSocketStrategyContext;

	public interface WsHandShakeHeader {

		String WS_COMMON_KEY = "Ws-Common-Key";

		String WS_AUTHORIZE_TOKEN = "Ws-Authorize-Token";

		String WS_ROLE = "Ws-Role";

		String WS_ID = "Ws-Id";

	}

	@Override
	public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		return null;
	}

	@Override
	public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		Tio.remove(channelContext, "websocket closed");
		return null;
	}

	@Override
	public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
		if (StrUtil.hasBlank(text)) {
			Tio.send(channelContext, WsResponse.fromText("Lack Of Params", "UTF-8"));
			return null;
		}
		log.info("【WebSocketHandler】接收到消息:{}", text);
		WebSocketRequest request = new Gson().fromJson(text, WebSocketRequest.class);
		PushBizType type = request.getType();
		WebSocketStrategyHandler scoreStrategy = webSocketStrategyContext.getHandle(type);
		if (scoreStrategy == null) {
			Tio.send(channelContext, WsResponse.fromText("非法消息,服务器即将断开连接", "UTF-8"));
			Tio.remove(channelContext, "websocket closed");
		}
		scoreStrategy.execute(request, channelContext);
		return null;
	}

	@Override
	public HttpResponse handshake(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext)
			throws Exception {
		// 握手签名校验
		String commonKey = httpRequest.getHeader(WsHandShakeHeader.WS_COMMON_KEY.toLowerCase());
		String authToken = httpRequest.getHeader(WsHandShakeHeader.WS_AUTHORIZE_TOKEN.toLowerCase());
		String roleType = httpRequest.getHeader(WsHandShakeHeader.WS_ROLE.toLowerCase());
		String uniqueId = httpRequest.getHeader(WsHandShakeHeader.WS_ID.toLowerCase());
		if (StrUtil.hasBlank(commonKey, authToken, roleType)) {
			httpResponse.setStatus(HttpResponseStatus.C401);
			return httpResponse;
		}
		Boolean verifyCommonKey = LocalCache.contains(commonKey);
		if (!verifyCommonKey) {
			httpResponse.setStatus(HttpResponseStatus.C401);
			return httpResponse;
		}
		Integer length = commonKey.length();
		String verifySeed = StrUtil.sub(commonKey, length >> 2, length >> 1);
		Boolean verifyResult = Transmitter.verify(verifySeed, authToken);
		if (!verifyResult) {
			httpResponse.setStatus(HttpResponseStatus.C401);
			return httpResponse;
		}
		Tio.bindUser(channelContext, uniqueId);
		return httpResponse;
	}

	@Override
	public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext)
			throws Exception {

	}
}
